from PyQt5.QtWidgets import *
from pyqtgraph import QtCore, QtGui
from PyQt5.QtWidgets import QVBoxLayout, QWidget, QDialog, QPushButton, QMessageBox
from threading import Thread
import os
import configparser
import globalvar

globalvar._init()
import importlib
import module_backtest

def dynamic_import(module):
    return importlib.import_module(module)
global dict_strategy, dict_strategyrun
dict_strategy = {}
dict_strategyrun = {}
global list_strategy, list_strategyrun
# 策略文件名称
list_strategy = ['MA策略', 'EMA策略', '3tick多空策略', '2根M1多空策略']
# 保存策略开启状态
list_strategyrun = [1, 1, 1, 1]
readstrategyinstrumentIDstaste = 1


def ReadStrategyInstrumentID(strategyname):
    # 每次TICK都读取，可改为只读取一次
    global dict_strategyinstrument
    global readstrategyinstrumentIDstaste
    if readstrategyinstrumentIDstaste == 1:
        readstrategyinstrumentIDstaste = 0
        dict_tick = {}
        globalvar.dict_strategyinstrument[strategyname] = dict_tick
        with open('strategyfile\\' + strategyname + '.csv', 'r') as f:
            for line in f:
                print(strategyname + ' 策略对以下合约生效： ' + line)
                linelist = line.strip('\n').split(',')
                for k in iter(linelist):
                    globalvar.dict_strategyinstrument[strategyname][k] = k
                    # print('读取策略'+strategyname+' 交易合约：'+globalvar.dict_strategyinstrument[strategyname][line])


def StrategyManager(marketdata):
    if globalvar.tradestate:
        # 定义跨模块全局变量
        globalvar.set_value('key1', 'Value1')
        globalvar.set_value('key2', 'Value2')
        '''
        module1 = dynamic_import('strategyfile.strategy1')
        module1.main(marketdata)
        module2 = dynamic_import('strategyfile.strategy2')
        module2.main(marketdata)
        return
        '''
        global list_strategy, list_strategyrun
        # 多个策略分别计算
        try:
            for k in list_strategy:
                # print("strategyfile (%s) %s" % (globalvar.ui.list_strategy.index(k) + 1, k))
                print("(%s) %s" % (list_strategy.index(k) + 1, k))
                if list_strategyrun[int(list_strategy.index(k))] == 1:
                    # print('允许运行该策略 %s' % k)
                    # 读取策略文件对应生效的合约文件，与策略文件同名，后缀名是.csv
                    ReadStrategyInstrumentID(k)
                    module = dynamic_import('strategyfile.' + k)
                    module.OnTick(marketdata, k)
        except Exception as e:
            print("StrategyManager Error:" + repr(e))


# 打开回测窗口
def Function_Clicked_BackTest():
    button = globalvar.ui.MainWindow.sender()
    if button:
        row = globalvar.ui.table_strategy.indexAt(button.pos()).row()
    # 打开合约组合
    if globalvar.DialogSetInstrumentState:
        return
    globalvar.DialogSetInstrumentState = True
    globalvar.DialogBackTestPoint = globalvar.ui.DialogBackTest(globalvar.ui.table_strategy.item(row, 1).text())
    globalvar.DialogBackTestPoint.setWindowTitle('量化回测参数设置（请随时关注回测模块更新http://www.vnpy.cn）：' + globalvar.ui.table_strategy.item(row, 1).text())
    globalvar.DialogBackTestPoint.show()
    screenRect = QApplication.desktop().screenGeometry()
    globalvar.DialogBackTestPoint.resize(max(1366, 0.70 * screenRect.width()), max(748, 0.70 * screenRect.height()))

    # 居中窗口
    screen = QDesktopWidget().screenGeometry()
    size = globalvar.DialogBackTestPoint.geometry()
    globalvar.DialogBackTestPoint.move((screen.width() - size.width()) / 2,
                                       (screen.height() - size.height()) / 2)
    globalvar.DialogBackTestPoint.exec_()


# 打开合约组选择窗口（设置策略的合约组，一共10个合约组）
def Function_Clicked_SetInsIrumentID():
    button = globalvar.ui.MainWindow.sender()
    if button:
        row = globalvar.ui.table_strategy.indexAt(button.pos()).row()
    # 打开合约组合
    # if globalvar.DialogTalibState:

    if globalvar.DialogSetInstrumentState:
        return
    globalvar.DialogSetInstrumentState = True
    dlg = globalvar.ui.DialogSetInstrumentID('')
    dlg.setWindowTitle('合约组列表：' + globalvar.ui.table_strategy.item(row, 1).text())
    dlg.show()
    screenRect = QApplication.desktop().screenGeometry()
    # dlg.resize(0.44 * screenRect.width(), 0.46 * screenRect.height())
    dlg.resize(860, 0.46 * screenRect.height())

    # 居中窗口
    screen = QDesktopWidget().screenGeometry()
    size = dlg.geometry()
    dlg.move((screen.width() - size.width()) / 2,
             (screen.height() - size.height()) / 2)
    dlg.exec_()


deleteButtonlist = []

def Function_ScanStrategy_SingleThreadPyManage():
    path = "strategyfile"
    ls = os.listdir(path)
    buttonid = 0
    for i in ls:
        c_path = os.path.join(path, i)
        if os.path.isdir(c_path):
            print(c_path)
            globalvar.ui.ClearPath(c_path)
        else:
            file = os.path.splitext(c_path)
            filename, type = file
            if type == ".py" or type == ".pyd" or type == ".pyc":
                if c_path in dict_strategy:
                    if dict_strategy[c_path] != globalvar.ui.fileTime(c_path):
                        print("修改了")
                else:
                    try:
                        filenameini = c_path
                        filenameini = filenameini.replace('py', 'ini')
                        #  实例化configParser对象
                        config = configparser.ConfigParser()
                        # -read读取ini文件
                        config.read(filenameini, encoding='utf-8')
                        if config.getint('setting', 'run') == 1:
                            dict_strategyrun[c_path] = 1
                        else:
                            dict_strategyrun[c_path] = 0
                        dict_strategy[c_path] = globalvar.ui.fileTime(c_path)
                        # print("find Strategy file:", c_path,globalvar.ui.fileTime(c_path))
                        row_cnt = globalvar.ui.table_strategy.rowCount()  # 返回当前行数（尾部）
                        # print("列数：",row_cnt)
                        globalvar.ui.table_strategy.insertRow(row_cnt)  # 尾部插入一行新行表格
                        column_cnt = globalvar.ui.table_strategy.columnCount()  # 返回当前列数
                        # for column in range(column_cnt):
                        item = QTableWidgetItem(str(row_cnt + 1))
                        if dict_strategyrun[c_path] == 1:
                            item.setCheckState(QtCore.Qt.Checked)
                        else:
                            item.setCheckState(QtCore.Qt.Unchecked)
                        globalvar.ui.table_strategy.setItem(row_cnt, 0, item)

                        item = QTableWidgetItem(str(c_path))
                        globalvar.ui.table_strategy.setItem(row_cnt, 1, item)
                        globalvar.ui.table_strategy.setItem(row_cnt, 2, item)
                        globalvar.ui.table_strategy.setItem(row_cnt, 3, item)
                        # buttonid="{} 设置合约".format(row_cnt)
                        # deleteButton = QPushButton("{} 设置合约".format(row_cnt))
                        deleteButton = QPushButton("选择合约组")
                        deleteButtonlist.append(deleteButton)
                        # deleteButton.clicked.connect(lambda:globalvar.ui.Function_delete_clicked(3))
                        deleteButton.clicked.connect(Function_Clicked_SetInsIrumentID)

                        buttonid = buttonid + 1
                        globalvar.ui.table_strategy.setCellWidget(row_cnt, 4, deleteButton)

                        deleteButton2 = QPushButton("编辑策略")
                        deleteButton2.clicked.connect(globalvar.ui.Function_doubleClicked_strategy)
                        globalvar.ui.table_strategy.setCellWidget(row_cnt, 5, deleteButton2)

                        deleteButton3 = QPushButton("回测")
                        deleteButton3.clicked.connect(Function_Clicked_BackTest)
                        globalvar.ui.table_strategy.setCellWidget(row_cnt, 6, deleteButton3)
                    except Exception as e:
                        print("Function_ScanStrategy_SingleThreadPyManage1 Error:" + repr(e))

                    # item2 = QtWidgets.QTableWidgetItem("1")
                    # item.setCheckState(QtCore.Qt.Unchecked)
                    # globalvar.ui.table_strategy.setItem(0, 0, item2)

                    # column_cnt = globalvar.ui.table_strategy.columnCount()  # 返回当前列数
                    # item = QtWidgets.table_strategy()
                    # globalvar.ui.table_strategy.setVerticalHeaderItem(1, item)

    try:
        for k in dict_strategy:
            print("(%s) %s" % (dict_strategy.index(k) + 1, k))
    except Exception as e:
        print("function_scanstrategy Error:" + repr(e))


# 多进程模式，由C++回调调用Python策略,支持文件类型：（1）.py（2）.dll
def Function_scanstrategy_MulitProcess():
    path = "strategyfile"
    ls = os.listdir(path)
    for i in ls:
        c_path = os.path.join(path, i)
        if os.path.isdir(c_path):
            print(c_path)
            globalvar.ui.ClearPath(c_path)
        else:
            file = os.path.splitext(c_path)
            filename, type = file
            if type == ".py" or type == ".pyd" or type == ".pyc":
                if c_path in dict_strategy:
                    if dict_strategy[c_path] != globalvar.ui.fileTime(c_path):
                        print("修改了")
                else:
                    try:
                        filenameini = c_path
                        filenameini = filenameini.replace('py', 'ini')
                        #  实例化configParser对象
                        config = configparser.ConfigParser()
                        # -read读取ini文件
                        config.read(filenameini, encoding='utf-8')
                        if config.getint('setting', 'run') == 1:
                            dict_strategyrun[c_path] = 1
                        else:
                            dict_strategyrun[c_path] = 0
                        dict_strategy[c_path] = globalvar.ui.fileTime(c_path)
                        # print("find Strategy file:", c_path,globalvar.ui.fileTime(c_path))
                        row_cnt = globalvar.ui.table_strategy.rowCount()  # 返回当前行数（尾部）
                        # print("列数：",row_cnt)
                        globalvar.ui.table_strategy.insertRow(row_cnt)  # 尾部插入一行新行表格
                        column_cnt = globalvar.ui.table_strategy.columnCount()  # 返回当前列数
                        # for column in range(column_cnt):
                        item = QTableWidgetItem(str(row_cnt + 1))
                        if dict_strategyrun[c_path] == 1:
                            item.setCheckState(QtCore.Qt.Checked)
                        else:
                            item.setCheckState(QtCore.Qt.Unchecked)
                        globalvar.ui.table_strategy.setItem(row_cnt, 0, item)
                        item = QTableWidgetItem(str("策略"))
                        globalvar.ui.table_strategy.setItem(row_cnt, 1, item)
                        item = QTableWidgetItem(str(c_path))
                        globalvar.ui.table_strategy.setItem(row_cnt, 2, item)
                        globalvar.ui.table_strategy.setItem(row_cnt, 3, item)
                        globalvar.ui.table_strategy.setItem(row_cnt, 4, item)
                        globalvar.ui.table_strategy.setItem(row_cnt, 5, item)

                    except:
                        pass

                    # item2 = QtWidgets.QTableWidgetItem("1")
                    # item.setCheckState(QtCore.Qt.Unchecked)
                    # globalvar.ui.table_strategy.setItem(0, 0, item2)

                    # column_cnt = globalvar.ui.table_strategy.columnCount()  # 返回当前列数
                    # item = QtWidgets.table_strategy()
                    # globalvar.ui.table_strategy.setVerticalHeaderItem(1, item)

    try:
        for k in dict_strategy:
            print("(%s) %s" % (dict_strategy.index(k) + 1, k))
    except Exception as e:
        print("function_scanstrategy Error:" + repr(e))


class MyStrategyMangement(object):
    # 多进程策略管理
    list_hwnd = []

    def StartStrategyProcess(self, msg):
        print("-->创建策略进程: ", msg[0], msg[1])
        sp = StrategyProcess(msg[0])
        thidprocesshwnd = sp.GetProcessHwnd()
        print('进程句柄返回值： ' + str(thidprocesshwnd))
        self.list_hwnd.append(thidprocesshwnd)
        return ("完成创建策略进程: " + msg[0])

    def CreatStrategyProcess(self):
        # 进程池，用于策略计算，将回调函数注册给C++ DLL，形成多个进程实例，在多进程下运行策略计算
        pool = multiprocessing.Pool(4)
        result = []
        for i in range(4):
            msg = ['MA策略.py', i]
            result.append(pool.apply_async(self.StartStrategyProcess, (msg,)))

        # pool.close()
        # pool.join()
        for res in result:
            print("-->进程返回值：", res.get())

    def GetStrategyMode(self):
        try:
            # 实例化configParser对象
            config = configparser.ConfigParser()
            # read读取ini文件
            config.read('VNStrategyProcess.ini', encoding='utf-8')
            if config.getint('setting', 'mode') == 1:
                print("当前策略模式：单线程模式执行策略运算，仅支持.py策略文件")
            elif config.getint('setting', 'mode') == 2:
                print("当前策略模式：C++策略管理器，C++多进程模式执行策略运算，支持.py策略文件和.dll策略文件")
                self.CreatStrategyProcess()
        except Exception as e:
            print("GetStrangeMode Error:" + repr(e))


class RegSpOnStrategyCalculate(Thread):
    def __init__(self, name, sp):
        super().__init__()
        self.name = name
        self.sp = sp

    def run(self):
        self.sp.VNRegOnStrategyCalculate()
